package io.dcloud.uniplugin;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicYuvToRGB;
import android.renderscript.Type;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;

import com.google.android.gms.tasks.OnSuccessListener;
import com.google.mlkit.vision.common.InputImage;
import com.google.mlkit.vision.text.Text;
import com.google.mlkit.vision.text.TextRecognition;
import com.google.mlkit.vision.text.TextRecognizer;
import com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;

import uni.dcloud.io.uniplugin_module.R;
import uni.dcloud.io.uniplugin_module.databinding.ActivityCameraBinding;


public class CameraActivity extends Activity {

    private ActivityCameraBinding binding;

    private CameraPreview preview;
    String TAG = "TestModule";
    private boolean isChecking = false; //是否在校验
    private boolean isCheckSuccess = false; //是否校验成功
    private int failCount = 0; //识别失败次数
    private String vinCode = "";
    private RenderScript rs;
    private ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic;
    private Type.Builder yuvType;
    private Type.Builder rgbaType;
    private Allocation allocation;
    private Allocation out;
    private Bitmap bitmap;

    /**
     * 相机预览
     */
    private FrameLayout mPreviewLayout;

    /**
     * 相机类
     */
    private Camera mCamera;

    /**
     * 图片流暂存
     */
    private byte[] imageData;

    /**
     * 预览数据流
     */
    private byte[] previewData;

    /**
     * 拍照标记
     */
    private boolean isTakePhoto = false;

    /**
     * 识别类型 ：0是拍照，1是车架号扫描
     */
    private int type;
    private String command;//口令

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityCameraBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        initData();
        initView();
        initRender();
        setOnclickListener();
    }

    private void initRender() {
        rs = RenderScript.create(this);
        yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
    }

    @Override
    protected void onResume() {
        super.onResume();
        mCamera = Camera.open(0);
        Log.d("预览数据", "开始预览");
        preview = new CameraPreview(this, mCamera);
        mPreviewLayout.addView(preview);
        mCamera.setPreviewCallback((data, camera) -> {
            previewData = data;
            if (!isChecking) {
                if (mCamera != null) {
                    mLoopHandler2.postDelayed(mLoopRunnable2, 0);
                } else {
                    mLoopHandler2.removeCallbacks(mLoopRunnable2);
                }
            }
        });
    }

    /**
     * 注释：设置监听事件
     */
    private void setOnclickListener() {
        binding.closeIv.setOnClickListener(v -> finish());
        binding.takeIv.setOnClickListener(v -> {
            if (!isCheckSuccess) {
                Toast.makeText(this, "请对准并拍摄清晰完整的车架号", Toast.LENGTH_SHORT).show();
                return;
            }
            if (!isTakePhoto) {
                takePhoto();
            }
        });

        binding.unselectIv.setOnClickListener(v -> {
            binding.takeIv.setVisibility(View.VISIBLE);
            binding.lightCb.setVisibility(View.VISIBLE);
            binding.idsGr.setVisibility(View.GONE);
            binding.idsGr.requestLayout();
            cancelSavePhoto();
        });


        // 打开补光灯
        binding.lightCb.setOnCheckedChangeListener((buttonView, isChecked) -> {
            Camera.Parameters mParameters = mCamera.getParameters();
            mParameters.setFlashMode(isChecked ? Camera.Parameters.FLASH_MODE_TORCH : Camera.Parameters.FLASH_MODE_OFF);
            mCamera.setParameters(mParameters);
        });

        binding.selectIv.setOnClickListener(v -> {
            binding.unselectIv.setVisibility(View.GONE);
            binding.selectIv.setVisibility(View.GONE);
            binding.idsGr.requestLayout();
            Runnable runnable = () -> savePhoto(bitmap);
            ThreadPoolInstance.getInstance().getThreadPoolExecutor().execute(runnable);
        });


        /**
         * 变焦
         */
        binding.setZoomBt.setOnClickListener(v -> {
            boolean isS = preview.isSupportZoom();
            if (isS) {
                preview.setZoom();
            }
        });
    }

    /**
     * 注释：拍照并保存图片到相册
     */
    private void takePhoto() {
        System.gc();
        try {
            isTakePhoto = true; //调用相机拍照
            mCamera.stopPreview();
            mLoopHandler.postDelayed(mLoopRunnable, 0);
        } catch (Exception e) {
        }
    }


    /**
     * 注释：取消保存
     */
    private void cancelSavePhoto() { //开始预览
        mCamera.startPreview();
        imageData = null;
        isTakePhoto = false;
    }

    /**
     * 注释：初始化视图
     */
    @SuppressLint("SetTextI18n")
    private void initView() {
        mPreviewLayout = findViewById(R.id.camera_preview_layout);
        binding.vinCodeTv.setText(vinCode);
        binding.commandTv.setText("口令：" + command);
        if (type == 0) {
            binding.titleTv.setVisibility(View.GONE);
            binding.takePhotoG.setVisibility(View.VISIBLE);
        } else {
            binding.titleTv.setVisibility(View.VISIBLE);
            binding.takePhotoG.setVisibility(View.GONE);
        }
    }

    /**
     * 初始化数据
     */
    private void initData() {
        Intent intent = getIntent();
        if (intent.hasExtra(VIN_CODE)) {
            vinCode = getIntent().getStringExtra(VIN_CODE);
        }
        type = getIntent().getIntExtra(TYPE, 0);
        command = getIntent().getStringExtra(COMMAND);
    }

    /**
     * 注释：保持图片
     */
    private void savePhoto(Bitmap retBitmap) {
        String cameraPath = Objects.requireNonNull(getExternalFilesDir("offline_package")).getAbsolutePath(); //相册文件夹
        File cameraFolder = new File(cameraPath);
        if (!cameraFolder.exists()) {
            cameraFolder.mkdirs();
        }
        CameraPreview.CameraSize cameraSize = preview.getCameraSize(); //保存的图片文件
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
        String imagePath = cameraFolder.getAbsolutePath() + File.separator + "IMG_" + simpleDateFormat.format(new Date()) + "(" + cameraSize.width + "x" + cameraSize.height + ")" + ".jpg";
        retBitmap = BitmapUtils.setTakePicktrueOrientation(Camera.CameraInfo.CAMERA_FACING_BACK, retBitmap);
        BitmapUtils.saveBitmap(retBitmap, imagePath);
        retBitmap.recycle();
        Intent intent = new Intent();
        intent.putExtra(PHOTO_PATH, imagePath);
        setResult(Activity.RESULT_OK, intent);
        Log.d(TAG, "图片路径：" + imagePath);
        //                    picCompress(imagePath)
        finish();
    }

    public static final String PHOTO_PATH = "图片路径";
    public static final String VIN_CODE = "车架号";
    public static final String COMMAND = "口令";
    public static final String TYPE = "识别类型";


    @Override
    protected void onPause() {
        super.onPause();
        super.onPause();
        preview.closeCamera();
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        super.onDestroy();
        preview.destroyDrawingCache(); //释放资源
    }

    /**
     * 鲁班图片压缩
     */
    private void picCompress(String path) {/* Luban.with(this).load(path).ignoreBy(100).setTargetDir(getPath()) //压缩文件缓存路径
            .setCompressListener(object : OnCompressListener {
                override fun onSuccess(file: File?) {

                    //                        deleteSingleFile(path)//删原始图片
                    println(file?.absolutePath)
                    val message = Message()
                    message.obj = file?.absolutePath ?: ""
                    handler.sendMessage(message)
                }

                override fun onError(e: Throwable?) {
                    val message = Message()
                    message.obj = path
                    handler.sendMessage(message)
                }

                override fun onStart() {
                }
            }).launch()*/
    }


    /**
     * 删除单个文件
     *
     * @param filePath 要删除的文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    private boolean deleteSingleFile(String filePath) {
        File file = new File(filePath); // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            return file.delete();
        } else {
            return false;
        }
    }

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            Intent intent = new Intent();
            intent.putExtra(PHOTO_PATH, msg.obj.toString());
            setResult(Activity.RESULT_OK, intent);
            finish();
        }
    };

    private Handler mLoopHandler = new Handler();
    private Runnable mLoopRunnable = new Runnable() {
        @Override
        public void run() {
            savePhoto(bitmap);
        }
    };

    private Handler mLoopHandler2 = new Handler();
    private Runnable mLoopRunnable2 = new Runnable() {
        @Override
        public void run() {
            long size = previewData.length == 0 ? 0 : previewData.length;
            if (size > 0) {
                isChecking = true;
                bitmap = convertBitmap4RenderScript(previewData);
                if (bitmap != null) {
                    Bitmap newBitMap = cropBitmapMiddle(bitmap);
                    processImage(newBitMap);
                    mLoopHandler2.removeCallbacks(this);
                }
            } else {
                isChecking = false;
            }
        }
    };

    /**
     * 裁剪bitmap
     */
    private Bitmap cropBitmapMiddle(Bitmap sourceBitmap) {
        int sourceWidth = sourceBitmap.getWidth();
        int sourceHeight = sourceBitmap.getHeight();

        // 计算裁剪区域的起始x坐标，确保裁剪的是中间160px宽的区域
        int startX = Math.max(0, (sourceWidth - 240) * 2 / 5);
        int startY = 0; // 从顶部开始裁剪
        int width = 240; // 裁剪宽度
        // 创建裁剪后的Bitmap
        return Bitmap.createBitmap(sourceBitmap, startX, startY, width, sourceHeight);
    }

    private Bitmap convertBitmap4RenderScript(byte[] data) {
        try {
            Camera.Size size = mCamera.getParameters().getPreviewSize();
            if (yuvType == null) {
                yuvType = new Type.Builder(rs, Element.U8(rs)).setX(data.length);
                allocation = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
            }
            if (rgbaType == null) {
                rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(size.width).setY(size.height);
                out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
            }
            allocation.copyFrom(data);
            yuvToRgbIntrinsic.setInput(allocation);
            yuvToRgbIntrinsic.forEach(out);
            Bitmap bitmap = Bitmap.createBitmap(size.width, size.height, Bitmap.Config.ARGB_8888);
            out.copyTo(bitmap);
            return bitmap;
        } catch (Exception e) {
            Log.e(TAG, e.toString());
            return null;
        }
    }

    // 假设你已经有了相机预览和处理图片的方法，在图片处理的回调中调用此方法来识别文本
    @SuppressLint("SetTextI18n")
    private void processImage(Bitmap bitmap) { // When using Chinese script library
        TextRecognizer recognizer = TextRecognition.getClient(new ChineseTextRecognizerOptions.Builder().build());
        InputImage image = InputImage.fromBitmap(bitmap, 0);
        recognizer.process(image).addOnSuccessListener(text -> {
            String content = text.getText().replace("I", "1").replace("O", "0");
            if (type == 0) {
                binding.contentTv.setText("识别内容：" + content);
                if (!vinCode.equals("") && content.contains(vinCode)) {
                    isCheckSuccess = true;
                    binding.line1.setBackgroundColor(ContextCompat.getColor(CameraActivity.this, R.color.green));
                    binding.line2.setBackgroundColor(ContextCompat.getColor(CameraActivity.this, R.color.green));
                    Log.d("ocr", "识别成功");
                    binding.warningContentTv.setTextColor(ContextCompat.getColor(CameraActivity.this, R.color.green));
                    binding.warningContentTv.setText("拍照成功");
                    takePhoto();
                } else {
                    failCount++;
                    if (failCount >= 40) {
                        failCount = 0;
                        isCheckSuccess = false;
                        Log.d("ocr", "识别失败");
                        binding.line1.setBackgroundColor(ContextCompat.getColor(CameraActivity.this, R.color.red));
                        binding.line2.setBackgroundColor(ContextCompat.getColor(CameraActivity.this, R.color.red));
                    }
                }
                isChecking = false;
            } else {
                String vin = getVin(content);
                if (!vin.equals("")) {
                    binding.line1.setBackgroundColor(ContextCompat.getColor(CameraActivity.this, R.color.green));
                    binding.line2.setBackgroundColor(ContextCompat.getColor(CameraActivity.this, R.color.green));
                    Log.d("ocr", "识别成功");
                    binding.warningContentTv.setTextColor(ContextCompat.getColor(CameraActivity.this, R.color.green));
                    binding.warningContentTv.setText("识别成功");
                    mCamera.stopPreview();
                    Intent intent = new Intent();
                    intent.putExtra(VIN_CODE, vin);
                    setResult(Activity.RESULT_OK, intent);
                    finish();
                } else {
                    isChecking = false;
                }
            }
            bitmap.recycle();
        });
    }

    private String getVin(String content) {
        for (int index = 0; index < content.length(); index++) {
            if (content.length() - index >= 17) {
                String vin = content.substring(index, index + 17);
                if (VinUtils.validFrameNumber(vin)) {
                    return vin;
                }
            }
        }
        return "";
    }
}
